/*
 * Copyright (c) 2010, Nikolaus Moll
 * All rights reserved.
 */
package net.miblounge.gradecalculator;

import java.io.File;
import java.io.FileFilter;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.List;

import net.miblounge.gradecalculator.core.descriptors.Descriptor;
import net.miblounge.gradecalculator.core.enums.CourseTypeDescriptor;
import net.miblounge.gradecalculator.core.enums.CourseTypeList;
import net.miblounge.gradecalculator.core.enums.ExaminationType;
import net.miblounge.gradecalculator.core.enums.ExaminationTypeDescriptor;
import net.miblounge.gradecalculator.core.enums.ExaminationTypeList;
import net.miblounge.gradecalculator.core.interfaces.IModuleListItem;
import net.miblounge.gradecalculator.core.olddescriptors.Course.CourseType;
import net.miblounge.gradecalculator.core.olddescriptors.Course.ExamType;

public final class Converter {

	private static final String BASE = "D:\\Projekte\\gradecalculator-workspace\\gradecalculator\\gradecalculator.gui\\resources\\universities\\Hochschule Ravensburg-Weingarten\\Bachelor\\";
	private static final String COURSE = "Elektrotechnik und Informationstechnik";
	
	//private static final String SOURCEFILE = BASE + COURSE + "SS2008.srdx.old";
	//private static final String DESTFILE = BASE + COURSE + "\\SS2008.srdx.new";
	//private static final String DESTFILE = "D:\\Projekte\\SS2008.srdx.txt";
	
	private Converter()
	{
	}
	
	public static ExaminationTypeList convertExamType(final ExamType oldType)
	{
		final ExaminationTypeList result = new ExaminationTypeList();
		for (ExaminationType t : ExaminationType.values()) {
			if (t.getAbbreviation().equals(oldType.toString())) {
				result.add(t);
			}
		}
		
		return result;
	}

	public static CourseTypeList convertCourseType(final EnumSet<CourseType> oldType)
	{
		final CourseTypeList result = new CourseTypeList();
		for (CourseType oldT : oldType) {
			boolean hit = false;
			for (net.miblounge.gradecalculator.core.enums.CourseType newT : net.miblounge.gradecalculator.core.enums.CourseType.values()) {
				if (newT.getAbbreviation().equals(oldT.toString())) {
					result.add(newT);
					hit = true;
					break;
				}
			}

			if (!hit) {
				//CHECKSTYLE:OFF
				System.out.println("Unkown course type: " + oldT);
				//CHECKSTYLE:ON
			}
		}
		
		return result;
	}

	public static net.miblounge.gradecalculator.core.descriptors.courses.IndividualCourse convertIndividualCourse(final net.miblounge.gradecalculator.core.olddescriptors.IndividualCourse oldCourse)
	{
		final net.miblounge.gradecalculator.core.descriptors.courses.IndividualCourse result = new net.miblounge.gradecalculator.core.descriptors.courses.IndividualCourse();
		
		result.setCourseNumber(oldCourse.getCourseNumber());
		result.setECTS(oldCourse.getECTS());
		result.setExamNumber(oldCourse.getExamNumber());
		
		result.setGradedPerformance(convertExamType(oldCourse.getGradedPerformance()));
		result.setUngradedPerformance(convertExamType(oldCourse.getUngradedPerformance()));

		result.setType(convertCourseType(oldCourse.getType()));
		
		result.setHoursPerWeek(oldCourse.getHoursPerWeek());
		result.setName(oldCourse.getName());
		result.setSemester(oldCourse.getSemester());
		result.setSortOrder(oldCourse.getSortOrder());
		
		return result;
	}
	
	public static net.miblounge.gradecalculator.core.descriptors.courses.Course convertCourse(final net.miblounge.gradecalculator.core.olddescriptors.Course oldCourse)
	{
		final net.miblounge.gradecalculator.core.descriptors.courses.Course result = new net.miblounge.gradecalculator.core.descriptors.courses.Course();
		
		result.setCourseNumber(oldCourse.getCourseNumber());
		result.setECTS(oldCourse.getECTS());
		result.setExamNumber(oldCourse.getExamNumber());
		
		result.setGradedPerformance(convertExamType(oldCourse.getGradedPerformance()));
		result.setUngradedPerformance(convertExamType(oldCourse.getUngradedPerformance()));

		result.setType(convertCourseType(oldCourse.getType()));
		
		result.setHoursPerWeek(oldCourse.getHoursPerWeek());
		result.setName(oldCourse.getName());
		result.setSemester(oldCourse.getSemester());
		result.setSortOrder(oldCourse.getSortOrder());
		
		return result;
	}
	
	public static net.miblounge.gradecalculator.core.descriptors.modulelistitems.Module convertModule(final net.miblounge.gradecalculator.core.olddescriptors.Module oldModule)
	{
		final net.miblounge.gradecalculator.core.descriptors.modulelistitems.Module result = new net.miblounge.gradecalculator.core.descriptors.modulelistitems.Module();
		
		result.setName(oldModule.getName());
		result.setSortOrder(oldModule.getSortOrder());
		
		for (net.miblounge.gradecalculator.core.olddescriptors.Course oldCourse : oldModule.getCourses()) {
			if (oldCourse instanceof net.miblounge.gradecalculator.core.olddescriptors.IndividualCourse) {
				result.addCourse(convertIndividualCourse((net.miblounge.gradecalculator.core.olddescriptors.IndividualCourse) oldCourse));
			} else {
				result.addCourse(convertCourse((net.miblounge.gradecalculator.core.olddescriptors.Course) oldCourse));
			}
		}
		
		return result;
	}
	
	public static net.miblounge.gradecalculator.core.descriptors.modulelistitems.SelectableModuleLists convertSelectableModuleLists(final net.miblounge.gradecalculator.core.olddescriptors.SelectableModuleLists oldModule)
	{
		final net.miblounge.gradecalculator.core.descriptors.modulelistitems.SelectableModuleLists result = new net.miblounge.gradecalculator.core.descriptors.modulelistitems.SelectableModuleLists();
		
		result.setName(oldModule.getName());
		result.setModuleListECTS(oldModule.getModuleListECTS());
		result.setPickCount(oldModule.getPickCount());
		result.setSortOrder(oldModule.getSortOrder());
		
		for (net.miblounge.gradecalculator.core.olddescriptors.ModuleList oldList : oldModule.getModuleLists()) {
			result.addModuleList(convertModuleList(oldList));
		}
		
		return result;
	}
	
	public static net.miblounge.gradecalculator.core.descriptors.modulelistitems.IndividualModule convertIndividualModule(final net.miblounge.gradecalculator.core.olddescriptors.IndividualModule oldModule)
	{
		final net.miblounge.gradecalculator.core.descriptors.modulelistitems.IndividualModule result = new net.miblounge.gradecalculator.core.descriptors.modulelistitems.IndividualModule();
		
		result.setName(oldModule.getName());
		result.setSortOrder(oldModule.getSortOrder());
		result.setECTS(oldModule.getECTS());
		result.setHoursPerWeek(oldModule.getHoursPerWeek());
		
		return result;
	}
	
	public static net.miblounge.gradecalculator.core.descriptors.modulelists.ModuleList convertModuleList(final net.miblounge.gradecalculator.core.olddescriptors.ModuleList oldList)
	{
		final net.miblounge.gradecalculator.core.descriptors.modulelists.ModuleList result = new net.miblounge.gradecalculator.core.descriptors.modulelists.ModuleList();
		
		result.setName(oldList.getName());
		result.setSortOrder(oldList.getSortOrder());
		
		for (IModuleListItem listItem : oldList.getModules()) {
			final IModuleListItem item; 
			if (listItem instanceof net.miblounge.gradecalculator.core.olddescriptors.IndividualModule) {
				item = convertIndividualModule((net.miblounge.gradecalculator.core.olddescriptors.IndividualModule)listItem);
			}
			else if (listItem instanceof net.miblounge.gradecalculator.core.olddescriptors.Module) {
				item = convertModule((net.miblounge.gradecalculator.core.olddescriptors.Module)listItem);
			}
			else if (listItem instanceof net.miblounge.gradecalculator.core.olddescriptors.SelectableModuleLists) {
				item = convertSelectableModuleLists((net.miblounge.gradecalculator.core.olddescriptors.SelectableModuleLists)listItem);
			} 
			else {
				item = null;
			}

			if (item == null) {
				throw new IllegalArgumentException("Invalid module type");
			}
			
			result.addModule(item);
		}
		
		return result;
	}
	
	public static void convertFile(final String source, final String dest)
	{
		final net.miblounge.gradecalculator.core.olddescriptors.StudyRegulationsDescription oldSPO = net.miblounge.gradecalculator.core.olddescriptors.StudyRegulationsDescription
				.createFromXML(source);

		final net.miblounge.gradecalculator.core.descriptors.StudyRegulationsDescription newSPO = new net.miblounge.gradecalculator.core.descriptors.StudyRegulationsDescription();

		newSPO.setDegree(oldSPO.getDegree());
		newSPO.setUniversity(oldSPO.getUniversity());
		newSPO.setSemester(oldSPO.getSemester());

		final List<ExaminationTypeDescriptor> examTypes = new ArrayList<ExaminationTypeDescriptor>();
		examTypes.add(new ExaminationTypeDescriptor("B", "Bachelor-Arbeit"));
		examTypes.add(new ExaminationTypeDescriptor("K", "Klausur"));
		examTypes.add(new ExaminationTypeDescriptor("M", "Muendlich"));
		examTypes.add(new ExaminationTypeDescriptor("R", "Referat"));
		examTypes.add(new ExaminationTypeDescriptor("PA", "Praktische Arbeit"));
		examTypes.add(new ExaminationTypeDescriptor("KQ", "Kolloqium"));
		newSPO.setExamTypes(examTypes);

		final List<CourseTypeDescriptor> courseTypes = new ArrayList<CourseTypeDescriptor>();
		courseTypes.add(new CourseTypeDescriptor("V", "Vorlesung"));
		courseTypes.add(new CourseTypeDescriptor("P", "Praktikum"));
		courseTypes.add(new CourseTypeDescriptor("S", "Seminar"));
		courseTypes.add(new CourseTypeDescriptor("PR", "Projekt"));
		newSPO.setCourseTypes(courseTypes);

		ExaminationType.reset();
		for (Descriptor d : examTypes) {
			ExaminationType.addExaminationType(d.getName(), d.getId());
		}

		net.miblounge.gradecalculator.core.enums.CourseType.reset();
		for (Descriptor d : courseTypes) {
			net.miblounge.gradecalculator.core.enums.CourseType
					.addCourseType(d.getName(), d.getId());
		}

		newSPO.setModuleList(convertModuleList(oldSPO.getModuleList()));

		newSPO.saveXML(dest);
	}

	/**
	 * @param args
	 */
	public static void main(final String[] args) {
		final File root = new File(BASE + COURSE);
		
		for (File file : root.listFiles(new FileFilter() {
			@Override
			public boolean accept(final File pathname) {
				if (pathname.isDirectory()) {
					return false;
				}
				
				return pathname.getAbsolutePath().endsWith(".srdx.old");
			}
		})) {
			final String sourceFile = file.getAbsolutePath();
			final String destFile = sourceFile.substring(0, sourceFile.length() - 4);
			//CHECKSTYLE:OFF
			System.out.println("Convering " + sourceFile);
			//CHECKSTYLE:ON
			
			convertFile(sourceFile, destFile);
		}
		
		//CHECKSTYLE:OFF
		System.out.println("fertig");
		//CHECKSTYLE:ON
	}

}
